package com.java.agent.enhance;

import net.bytebuddy.description.NamedElement;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.MethodDelegation;
import net.bytebuddy.matcher.ElementMatcher;
import net.bytebuddy.utility.JavaModule;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import static net.bytebuddy.matcher.ElementMatchers.named;

public abstract class BaseDefiner {

    private static Map<String, BaseDefiner> runtime = new HashMap<>();

    public static BaseDefiner getRuntime(String key) {
        return runtime.get(key);
    }

    public BaseDefiner(String className){
        runtime.put(className,this);
    }

    public abstract     String getClassName();

    public abstract     String getMentodName();

    public abstract     String getAnnotation();

    public abstract     String getEnhancedClass();

    public static ElementMatcher<? super TypeDescription> matchs() {
        ElementMatcher.Junction.AbstractBase judge = new ElementMatcher.Junction.AbstractBase<NamedElement>() {

            @Override
            public boolean matches(NamedElement target) {
                return runtime.containsKey(target.getActualName());
            }
        };
        runtime.forEach((key,value)->judge.or(named(value.getClassName())));

        return judge;
    }

    public   DynamicType.Builder<?>  enhanced(DynamicType.Builder<?> builder,
                                                       TypeDescription typeDescription,
                                                       ClassLoader classLoader,
                                                       JavaModule module) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException, Exception {
        return builder.method(named( getMentodName())).intercept(MethodDelegation.to(Class.forName(getEnhancedClass()).getDeclaredConstructor().newInstance()));
    }
}
